/**
 * { data-analysis:  ['read', 'write'] }
 */

export type UserPermission = Record<string, string[]>;

type Auth = {
	resource: string | RegExp;
	actions?: string[];
};

export interface AuthParams {
	requiredPermissions?: Array<Auth>;
	oneOfPerm?: boolean;
}

const judge = (actions: string[], perm: string[]) => {
	if (!perm || !perm.length) {
		return false;
	}

	if (perm.join("") === "*") {
		return true;
	}

	return actions.every(action => perm.includes(action));
};

const auth = (params: Auth, userPermission: UserPermission) => {
	const { resource, actions = [] } = params;
	if (resource instanceof RegExp) {
		const permKeys = Object.keys(userPermission);
		const matchPermissions = permKeys.filter(item => item.match(resource));

		return matchPermissions.every(key => {
			const perm = userPermission[key];
			return judge(actions, perm);
		});
	}

	const perm = userPermission[resource];
	return judge(actions, perm);
};

export default (params: AuthParams, userPermission: UserPermission) => {
	const { requiredPermissions, oneOfPerm } = params;
	if (Array.isArray(requiredPermissions) && requiredPermissions.length) {
		let count = 0;
		for (const rp of requiredPermissions) {
			if (auth(rp, userPermission)) {
				count++;
			}
		}
		return oneOfPerm ? count > 0 : count === requiredPermissions.length;
	}
	return true;
};
